/**
 * @Author: DengLibin
 * @Date: Create in 2022-12-01 09:27:38
 * @Description: http客户端
 */
package util

import (
	"bufio"
	"bytes"
	"encoding/json"

	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path"
	"strings"
	"sync"
	"time"

	"gitee.com/DengLibin/go-common-util.git/log"
	"github.com/sirupsen/logrus"
)

var client *http.Client
var once sync.Once

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-05 17:45:26
 * @Description: 初始化httpclient
 */
func initClient() {
	once.Do(func() {
		log.Init()
		client = http.DefaultClient
		client.Timeout = time.Second * 60 //设置超时时间
		logrus.Info("初始化httpclient")
	})

}

/**
 * @Author: DengLibin
 * @Date: Create in 2022-12-01 09:28:25
 * @Description: 下载文件
 */
func DownFile(durl, filepath string) error {
	initClient()
	log.Init()
	uri, err := url.ParseRequestURI(durl)
	if err != nil {
		return err
	}
	filename := path.Base(uri.Path)
	logrus.Info("下载文件:", filename)

	resp, err := client.Get(durl)
	if err != nil {
		return err
	}
	body := resp.Body
	defer body.Close()

	reader := bufio.NewReaderSize(body, 1024*32)

	file, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer file.Close()
	writer := bufio.NewWriter(file)

	buff := make([]byte, 32*1024)
	written := 0

	for {
		nr, err := reader.Read(buff)
		if err != nil {
			//读取完毕
			if err == io.EOF {
				break
			}
			return err
		}
		if nr > 0 {
			nw, ew := writer.Write(buff[0:nr])

			if ew != nil {
				return ew
			}
			if nw > 0 {
				written += nw
			}

			if nr != nw {
				err = io.ErrShortWrite
				return err
			}
		}
	}
	return nil
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-05 17:47:29
 * @Description: get请求
 */
func DoGet(getUrl string) (string, error) {
	initClient()
	_, err := url.ParseRequestURI(getUrl)
	if err != nil {
		return "", err
	}

	resp, err := client.Get(getUrl)
	if err != nil {
		return "", err
	}
	body := resp.Body
	defer body.Close()

	bytes, err := io.ReadAll(body)
	if err != nil {
		return "", err
	}
	return string(bytes), nil

}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-05 17:57:36
 * @Description: post 请求
 */
func DoPostForm(postUrl string, params map[string][]string) (string, error) {
	initClient()
	_, err := url.ParseRequestURI(postUrl)
	if err != nil {
		return "", err
	}

	resp, err := http.PostForm(postUrl, params)

	if err != nil {
		return "", err
	}

	defer resp.Body.Close()
	bytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(bytes), nil

}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-06 09:01:55
 * @Description: request 请求
 * @requestMethod： 请求方式 POST GET ...
 * @url: url
 * @header: 请求头 可为nil ["Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"] ["Cookie", "name=anny"]
 * @body: 参数
 */
func DoPostReqeust(url string, header map[string]string, body string) (string, error) {
	initClient()
	req, err := http.NewRequest("POST", url, strings.NewReader(body))
	if err != nil {
		return "", err
	}

	for k, v := range header {
		req.Header.Set(k, v)
	}

	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	bytes, err := io.ReadAll(resp.Body)

	if err != nil {
		return "", err
	}
	return string(bytes), nil

}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-06 09:17:56
 * @Description: 提交json对象
 */
func DoPostJSON(url string, header map[string]string, obj interface{}) (string, error) {
	initClient()
	b, err := json.Marshal(&obj)
	if err != nil {
		return "", nil
	}
	body := string(b)
	req, err := http.NewRequest("POST", url, strings.NewReader(body))
	if err != nil {
		return "", err
	}

	for k, v := range header {
		req.Header.Set(k, v)
	}

	req.Header.Set("Content-Type", "application/json;charset=UTF-8")

	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	bytes, err := io.ReadAll(resp.Body)

	if err != nil {
		return "", err
	}
	return string(bytes), nil

}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-06 09:44:18
 * @Description: 上传单个文件
 * @header: 请求头
 * @param: 参数名
 * @filePath: 文件路径
 * @fileName: 文件名
 */
func UploadOneFile(uploadUrl string, header map[string]string, paramName string, filePath string, fileName string) (string, error) {
	initClient()

	bodyBuffer := &bytes.Buffer{}
	bodyWriter := multipart.NewWriter(bodyBuffer)

	fileWriter, _ := bodyWriter.CreateFormFile(paramName, fileName)
	file, _ := os.Open(filePath)
	defer file.Close()
	io.Copy(fileWriter, file)

	// file2 多个文件
	// fileWriter2, _ := bodyWriter.CreateFormFile("files", "file2.txt")
	// file2, _ := os.Open("file2.txt")
	// defer file2.Close()
	// io.Copy(fileWriter2, file2)

	//其他参数
	//bodyWriter.WriteField(key, value)

	contentType := bodyWriter.FormDataContentType()
	bodyWriter.Close()

	//resp, err := http.Post(uploadUrl, contentType, bodyBuffer)

	req, err := http.NewRequest("POST", uploadUrl, bodyBuffer)
	if err != nil {
		return "", err
	}
	for k, v := range header {
		req.Header.Set(k, v)
	}
	req.Header.Set("Content-Type", contentType)
	resp, err := client.Do(req)

	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	bytes, err := io.ReadAll(resp.Body)

	if err != nil {
		return "", err
	}
	return string(bytes), nil
}
